package com.ruoyi.common.utils.digest;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import org.springframework.util.Base64Utils;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.ByteArrayOutputStream;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
import java.util.Map;
import java.util.regex.Pattern;

public class Pwd {

    public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
        String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVfisoOLrHQTZcAoQgKs36C0tOA4Kn6O6mYTxtBntO9dH/F+qYYXkNw8YJe2qDVIECeZSjgIZvsqItui9sJYNDAlIwW8QUguLjzrP/uJs9XjuniUvvDEEyTDBUOqUUr8164RUgGjt/7GhD5/EPnmir0hnji4bsP3bZX7QK6uOhUwIDAQAB";
        String testStr = "TEST10494";//TEST0602

        String string = getPwd(publicKey, testStr);

//        String string = getPwd(publicKey, testStr);
        System.out.println(string);
    }

    public static String getSign(String signKey, String str) {
//        String str = "{\n" +
//                " \"username\":\"j6nSKF6bT2dww7Y25h+JYHGz4CJEEzBPyvxlFu5C/ZMzMw7SXRNQT6pmD86xB/YqAU97fV+WouCGtS4Tf3b6weYHXBYSu6WSgu8MeWW6ui4NekXsTYlTcEWkVplMZSdRJeJysT6Squ3t18fwYQTBcAKVB07MGGyUufYP6xE5hMI=\",\n" +
//                " \"password\":\"SsQ+HCMt1P7c3bi/1vElVlZTfV9HQvfqNIAZENhXAnxwj+FNcwaGKU9+XtTbsoNvZp3B+7JO0tVCSjsnIiXGDlgrXw5vnhl0rQpj3ecbCRTp0wTkP037CoVYqt5OZTpcjL70LfCkEnWN2Ax4UlSw1LoxcR/idXwLHolhHoYbQGs=\"\n" +
//                "}";

        //生成json
        String string = null;
        try {
            //清除换行符
            str = Pattern.compile("[\t\r\n]").matcher(str).replaceAll("");

            //jaskson解析
            ObjectMapper OBJECT_MAPPER = new ObjectMapper();

            //转成map
            Map jsonNode = OBJECT_MAPPER.readValue(str, Map.class);

            //排序
            OBJECT_MAPPER.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);
            string = OBJECT_MAPPER.writeValueAsString(jsonNode);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //HmacSHA265 加密
        return DigestUtil.hmacDegist(DigestUtil.HmacSHA256, signKey.getBytes(), string).toBase64();
    }

    public static String getPwd(String publicKey, String testStr) {

        byte[] result = new byte[0];
        try {
            byte[] data = testStr.getBytes(Charset.forName("utf-8"));
            byte[] keyBytes = Base64Utils.decode(publicKey.getBytes(Charset.forName("utf-8")));
            X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PublicKey key = keyFactory.generatePublic(x509KeySpec);
            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            cipher.init(Cipher.ENCRYPT_MODE, key);
            result = doFinal(cipher, data, 128 - 11);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //加密后的字符
        return new String(java.util.Base64.getEncoder().encode(result), StandardCharsets.UTF_8);
    }

    private static byte[] doFinal(Cipher cipher, byte[] data, int key_len) throws BadPaddingException, IllegalBlockSizeException {
        int inputLen = data.length, offset = 0;
        byte[] tmp;
        ByteArrayOutputStream out = new ByteArrayOutputStream(getTmpArrayLength(inputLen));
        while (inputLen > 0) {
            tmp = cipher.doFinal(data, offset, Math.min(key_len, inputLen));
            out.write(tmp, 0, tmp.length);
            offset += key_len;
            inputLen -= key_len;
        }
        return out.toByteArray();
    }

    private static int getTmpArrayLength(int L) {
        int S = 128;
        while (S < L) S <<= 1;
        return S;
    }
}
